From 18a46302a43f513e73baa470c7c7dfc74e1631d5 Mon Sep 17 00:00:00 2001 From: "smh22@labyrinth.cl.cam.ac.uk" Date: Mon, 10 Nov 2003 18:02:48 +0000 Subject: [PATCH] bitkeeper revision 1.580.1.1 (3fafd2c85ofrHsrmRaYOxYp49iwWOA) new vbd probe world --- BitKeeper/etc/ignore | 5 + tools/internal/Makefile | 1 + tools/internal/xi_phys_grant.c | 20 +- xen/drivers/block/xen_block.c | 90 ++----- xen/drivers/block/xen_vbd.c | 227 ++++++++++++++---- xen/drivers/ide/ide-xeno.c | 53 ++-- xen/drivers/scsi/sd.c | 39 +-- xen/include/hypervisor-ifs/block.h | 14 +- xen/include/hypervisor-ifs/vbd.h | 49 ++-- xen/include/xeno/vbd.h | 10 +- .../arch/xeno/drivers/block/xl_block.c | 36 ++- .../arch/xeno/drivers/dom0/dom0_core.c | 35 --- 12 files changed, 343 insertions(+), 236 deletions(-) diff --git a/BitKeeper/etc/ignore b/BitKeeper/etc/ignore index 2ca7761ef4..171cca7f9b 100644 --- a/BitKeeper/etc/ignore +++ b/BitKeeper/etc/ignore @@ -483,3 +483,8 @@ xen/common/debug.c~ xen/common/debug.o tools/internal/xi_restore_linux tools/internal/xi_save_linux +tools/internal/xi_vbd_add +tools/internal/xi_vbd_create +tools/internal/xi_vbd_info +tools/internal/xi_vbd_list +xen/drivers/scsi/BusLogic.o diff --git a/tools/internal/Makefile b/tools/internal/Makefile index 03a36dc277..3979cace5b 100644 --- a/tools/internal/Makefile +++ b/tools/internal/Makefile @@ -10,6 +10,7 @@ OBJS = $(patsubst %.c,%.o,$(SRCS)) TARGETS = xi_create xi_start xi_stop xi_destroy xi_build TARGETS += xi_phys_grant xi_list xi_save_linux xi_restore_linux TARGETS += xi_sched_global xi_sched_domain xi_usage xi_vif_params +TARGETS += xi_vbd_create xi_vbd_add xi_vbd_list xi_vbd_info INSTALL = $(TARGETS) xi_vifinit xi_helper all: check-for-zlib $(TARGETS) diff --git a/tools/internal/xi_phys_grant.c b/tools/internal/xi_phys_grant.c index c5a608ce61..9f24ff56b0 100644 --- a/tools/internal/xi_phys_grant.c +++ b/tools/internal/xi_phys_grant.c @@ -30,13 +30,13 @@ int main(int argc, char *argv[]) vdevice = device + atoi(argv[6]); op.cmd = BLOCK_IO_OP_VBD_CREATE; - op.u.create_info.domain = domain; - op.u.create_info.vdevice = vdevice; - op.u.create_info.mode = 0; + op.u.create_params.domain = domain; + op.u.create_params.vdevice = vdevice; + op.u.create_params.mode = 0; if ( strchr(argv[1], 'r') ) - op.u.create_info.mode |= VBD_MODE_R; + op.u.create_params.mode |= VBD_MODE_R; if ( strchr(argv[1], 'w') ) - op.u.create_info.mode |= VBD_MODE_W; + op.u.create_params.mode |= VBD_MODE_W; ret = do_block_io_op(&op); @@ -48,12 +48,12 @@ int main(int argc, char *argv[]) op.cmd = BLOCK_IO_OP_VBD_ADD; - op.u.add_info.domain = domain; - op.u.add_info.vdevice = vdevice; + op.u.add_params.domain = domain; + op.u.add_params.vdevice = vdevice; - op.u.add_info.extent.device = device; - op.u.add_info.extent.start_sector = atol(argv[4]); - op.u.add_info.extent.nr_sectors = atol(argv[5]); + op.u.add_params.extent.device = device; + op.u.add_params.extent.start_sector = atol(argv[4]); + op.u.add_params.extent.nr_sectors = atol(argv[5]); ret = do_block_io_op(&op); diff --git a/xen/drivers/block/xen_block.c b/xen/drivers/block/xen_block.c index 034c5edc75..d157212271 100644 --- a/xen/drivers/block/xen_block.c +++ b/xen/drivers/block/xen_block.c @@ -73,7 +73,6 @@ static void unlock_buffer(struct task_struct *p, static void io_schedule(unsigned long unused); static int do_block_io_op_domain(struct task_struct *p, int max_to_do); static void dispatch_rw_block_io(struct task_struct *p, int index); -static void dispatch_probe(struct task_struct *p, int index); static void dispatch_debug_block_io(struct task_struct *p, int index); static void make_response(struct task_struct *p, unsigned long id, unsigned short op, unsigned long st); @@ -241,31 +240,35 @@ long do_block_io_op(block_io_op_t *u_block_io_op) break; case BLOCK_IO_OP_VBD_CREATE: - /* create a new VBD for a given domain; caller must be privileged */ - if(!IS_PRIV(p)) - return -EPERM; - ret = vbd_create(&op.u.create_info); + /* create a new VBD */ + ret = vbd_create(&op.u.create_params); break; case BLOCK_IO_OP_VBD_ADD: - /* add an extent to a VBD; caller must be privileged */ - if(!IS_PRIV(p)) - return -EPERM; - ret = vbd_add(&op.u.add_info); + /* add an extent to a VBD */ + ret = vbd_add(&op.u.add_params); break; case BLOCK_IO_OP_VBD_REMOVE: - /* remove an extent from a VBD; caller must be privileged */ - if(!IS_PRIV(p)) - return -EPERM; - ret = vbd_remove(&op.u.remove_info); + /* remove an extent from a VBD */ + ret = vbd_remove(&op.u.remove_params); break; case BLOCK_IO_OP_VBD_DELETE: - /* delete a VBD; caller must be privileged */ - if(!IS_PRIV(p)) - return -EPERM; - ret = vbd_delete(&op.u.delete_info); + /* delete a VBD */ + ret = vbd_delete(&op.u.delete_params); + break; + + case BLOCK_IO_OP_VBD_PROBE: + /* query VBD information for self or others (or all) */ + ret = vbd_probe(&op.u.probe_params); + if(ret == 0) + copy_to_user(u_block_io_op, &op, sizeof(op)); + break; + + case BLOCK_IO_OP_VBD_INFO: + /* query information about a particular VBD */ + ret = vbd_info(&op.u.info_params); break; default: @@ -403,10 +406,6 @@ static int do_block_io_op_domain(struct task_struct *p, int max_to_do) dispatch_rw_block_io(p, i); break; - case XEN_BLOCK_PROBE: - dispatch_probe(p, i); - break; - case XEN_BLOCK_DEBUG: dispatch_debug_block_io(p, i); break; @@ -429,55 +428,6 @@ static void dispatch_debug_block_io(struct task_struct *p, int index) DPRINTK("dispatch_debug_block_io: unimplemented\n"); } - -static void dispatch_probe(struct task_struct *p, int index) -{ - extern void ide_probe_devices(xen_disk_info_t *xdi); - extern void scsi_probe_devices(xen_disk_info_t *xdi); - extern void vbd_probe_devices(xen_disk_info_t *xdi, struct task_struct *p); - - blk_ring_t *blk_ring = p->blk_ring_base; - xen_disk_info_t *xdi; - unsigned long flags, buffer; - int rc = 0; - - buffer = blk_ring->ring[index].req.buffer_and_sects[0] & ~0x1FF; - - spin_lock_irqsave(&p->page_lock, flags); - if ( !__buffer_is_valid(p, buffer, sizeof(xen_disk_info_t), 1) ) - { - DPRINTK("Bad buffer in dispatch_probe_blk\n"); - spin_unlock_irqrestore(&p->page_lock, flags); - rc = 1; - goto out; - } - - __lock_buffer(buffer, sizeof(xen_disk_info_t), 1); - spin_unlock_irqrestore(&p->page_lock, flags); - - /* - ** XXX SMH: all three of the below probe functions /append/ their - ** info to the xdi array; i.e. they assume that all earlier slots - ** are correctly filled, and that xdi->count points to the first - ** free entry in the array. All kinda gross but it'll do for now. - */ - xdi = map_domain_mem(buffer); - xdi->count = 0; - - if(IS_PRIV(p)) { - /* privileged domains always get access to the 'real' devices */ - ide_probe_devices(xdi); - scsi_probe_devices(xdi); - } - vbd_probe_devices(xdi, p); - unmap_domain_mem(xdi); - - unlock_buffer(p, buffer, sizeof(xen_disk_info_t), 1); - - out: - make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE, rc); -} - static void dispatch_rw_block_io(struct task_struct *p, int index) { extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]); diff --git a/xen/drivers/block/xen_vbd.c b/xen/drivers/block/xen_vbd.c index 8ac4f889a7..a4431a8559 100644 --- a/xen/drivers/block/xen_vbd.c +++ b/xen/drivers/block/xen_vbd.c @@ -14,6 +14,15 @@ #include #include +/* +** XXX SMH: the below probe functions /append/ their info to the +** xdi array; i.e. they assume that all earlier slots are correctly +** filled, and that xdi->count points to the first free entry in +** the array. All kinda gross but it'll do for now. +*/ +extern int ide_probe_devices(xen_disk_info_t *xdi); +extern int scsi_probe_devices(xen_disk_info_t *xdi); + #if 0 #define DPRINTK(_f, _a...) printk( _f , ## _a ) @@ -27,29 +36,32 @@ /* ** Create a new VBD; all this involves is adding an entry to the domain's -** vbd hash table. +** vbd hash table; caller must be privileged. */ -long vbd_create(vbd_create_t *create_info) +long vbd_create(vbd_create_t *create_params) { struct task_struct *p; vbd_t *new_vbd, *v; int h; - p = find_domain_by_id(create_info->domain); + if(!IS_PRIV(current)) + return -EPERM; + + p = find_domain_by_id(create_params->domain); if (!p) { printk("vbd_create attempted for non-existent domain %d\n", - create_info->domain); + create_params->domain); return -EINVAL; } new_vbd = kmalloc(sizeof(vbd_t), GFP_KERNEL); - new_vbd->vdevice = create_info->vdevice; - new_vbd->mode = create_info->mode; + new_vbd->vdevice = create_params->vdevice; + new_vbd->mode = create_params->mode; new_vbd->extents = (xen_extent_le_t *)NULL; new_vbd->next = (vbd_t *)NULL; - h = HSH(create_info->vdevice); + h = HSH(create_params->vdevice); if(p->vbdtab[h]) { for(v = p->vbdtab[h]; v->next; v = v->next) ; @@ -65,25 +77,28 @@ long vbd_create(vbd_create_t *create_info) ** Add an extent to an existing VBD; fails if the VBD doesn't exist. ** Doesn't worry about overlapping extents (e.g. merging etc) for now. */ -long vbd_add(vbd_add_t *add_info) +long vbd_add(vbd_add_t *add_params) { struct task_struct *p; xen_extent_le_t *x, *xele; vbd_t *v; int h; - p = find_domain_by_id(add_info->domain); + if(!IS_PRIV(current)) + return -EPERM; + + p = find_domain_by_id(add_params->domain); if (!p) { printk("vbd_add attempted for non-existent domain %d\n", - add_info->domain); + add_params->domain); return -EINVAL; } - h = HSH(add_info->vdevice); + h = HSH(add_params->vdevice); for(v = p->vbdtab[h]; v; v = v->next) - if(v->vdevice == add_info->vdevice) + if(v->vdevice == add_params->vdevice) break; if(!v) { @@ -92,9 +107,9 @@ long vbd_add(vbd_add_t *add_info) } xele = kmalloc(sizeof(xen_extent_le_t), GFP_KERNEL); - xele->extent.device = add_info->extent.device; - xele->extent.start_sector = add_info->extent.start_sector; - xele->extent.nr_sectors = add_info->extent.nr_sectors; + xele->extent.device = add_params->extent.device; + xele->extent.start_sector = add_params->extent.start_sector; + xele->extent.nr_sectors = add_params->extent.nr_sectors; xele->next = (xen_extent_le_t *)NULL; if(!v->extents) { @@ -109,12 +124,157 @@ long vbd_add(vbd_add_t *add_info) return 0; } -long vbd_remove(vbd_remove_t *remove_info) +long vbd_remove(vbd_remove_t *remove_params) { + if(!IS_PRIV(current)) + return -EPERM; + return -ENOSYS; } -long vbd_delete(vbd_delete_t *delete_info) +long vbd_delete(vbd_delete_t *delete_params) +{ + if(!IS_PRIV(current)) + return -EPERM; + + return -ENOSYS; +} + + +/* + * vbd_probe_devices: + * + * add the virtual block devices for this domain to a xen_disk_info_t; + * we assume xdi->count points to the first unused place in the array. + */ +static int vbd_probe_devices(xen_disk_info_t *xdi, struct task_struct *p) +{ + xen_extent_le_t *x; + xen_disk_t cur_disk; + vbd_t *v; + int i, ret; + + for(i = 0; i < VBD_HTAB_SZ; i++) { + + for(v = p->vbdtab[i]; v; v = v->next) { + + /* SMH: don't ever expect this to happen, hence verbose printk */ + if ( xdi->count == xdi->max ) { + printk("vbd_probe_devices: out of space for probe.\n"); + return -ENOMEM; + } + + cur_disk.device = v->vdevice; + cur_disk.info = XD_FLAG_VIRT | XD_TYPE_DISK; + if(!VBD_CAN_WRITE(v)) + cur_disk.info |= XD_FLAG_RO; + cur_disk.capacity = 0 ; + for(x = v->extents; x; x = x->next) + cur_disk.capacity += x->extent.nr_sectors; + cur_disk.domain = p->domain; + + /* Now copy into relevant part of user-space buffer */ + if((ret = copy_to_user(xdi->disks + xdi->count, &cur_disk, + sizeof(xen_disk_t))) < 0) { + printk("vbd_probe_devices: copy_to_user failed [rc=%d]\n", + ret); + return ret; + } + + + xdi->count++; + } + } + + return 0; +} + + +/* +** Return information about the VBDs available for a given domain, +** or for all domains; in the general case the 'domain' argument +** will be 0 which means "information about the caller"; otherwise +** the 'domain' argument will specify either a given domain, or +** all domains ("VBD_PROBE_ALL") -- both of these cases require the +** caller to be privileged. +*/ +long vbd_probe(vbd_probe_t *probe_params) +{ + struct task_struct *p = NULL; + int ret; + + if(probe_params->domain) { + + /* we can only probe for ourselves unless we're privileged */ + if(probe_params->domain != current->domain && !IS_PRIV(current)) + return -EPERM; + + if(probe_params->domain != VBD_PROBE_ALL) { + + p = find_domain_by_id(probe_params->domain); + + if (!p) { + printk("vbd_probe attempted for non-existent domain %d\n", + probe_params->domain); + return -EINVAL; + } + + } + + } else + /* default is to probe for ourselves */ + p = current; + + + if(!p || IS_PRIV(p)) { + + /* privileged domains always get access to the 'real' devices */ + if((ret = ide_probe_devices(&probe_params->xdi))) { + printk("vbd_probe: error %d in probing ide devices\n", ret); + return ret; + } + if((ret = scsi_probe_devices(&probe_params->xdi))) { + printk("vbd_probe: error %d in probing scsi devices\n", ret); + return ret; + } + } + + + if(!p) { + + u_long flags; + + read_lock_irqsave (&tasklist_lock, flags); + + p = &idle0_task; + while ( (p = p->next_task) != &idle0_task ) { + if (!is_idle_task(p)) { + if((ret = vbd_probe_devices(&probe_params->xdi, p))) { + printk("vbd_probe: error %d in probing virtual devices\n", + ret); + read_unlock_irqrestore(&tasklist_lock, flags); + return ret; + } + } + } + + read_unlock_irqrestore(&tasklist_lock, flags); + + } else { + + /* probe for disks and VBDs for just 'p' */ + if((ret = vbd_probe_devices(&probe_params->xdi, p))) { + printk("vbd_probe: error %d in probing virtual devices\n", ret); + return ret; + } + + } + + + return 0; +} + +long vbd_info(vbd_info_t *info_params) { return -ENOSYS; } @@ -173,39 +333,6 @@ int vbd_translate(phys_seg_t * pseg, int *nr_segs, } -/* - * vbd_probe_devices: - * - * add the virtual block devices for this domain to a xen_disk_info_t; - * we assume xdi->count points to the first unused place in the array. - */ -void vbd_probe_devices(xen_disk_info_t *xdi, struct task_struct *p) -{ - xen_extent_le_t *x; - vbd_t *v; - int i; - - /* XXX SMH: should allow priv domains to probe vbds for other doms XXX */ - - for(i = 0; i < VBD_HTAB_SZ; i++) { - for(v = p->vbdtab[i]; v; v = v->next) { - - xdi->disks[xdi->count].device = v->vdevice; - xdi->disks[xdi->count].info = XD_FLAG_VIRT | XD_TYPE_DISK; - - if(!VBD_CAN_WRITE(v)) - xdi->disks[xdi->count].info |= XD_FLAG_RO; - - xdi->disks[xdi->count].capacity = 0; - for(x = v->extents; x; x = x->next) - xdi->disks[xdi->count].capacity += x->extent.nr_sectors; - xdi->count++; - } - } - - return; -} - diff --git a/xen/drivers/ide/ide-xeno.c b/xen/drivers/ide/ide-xeno.c index abc94060a1..69df07964d 100644 --- a/xen/drivers/ide/ide-xeno.c +++ b/xen/drivers/ide/ide-xeno.c @@ -24,14 +24,14 @@ static kdev_t ide_devs[NR_IDE_DEVS] = { -void ide_probe_devices(xen_disk_info_t* xdi) +int ide_probe_devices(xen_disk_info_t* xdi) { - int loop; + int loop, ret = 0; unsigned int unit; - unsigned long capacity; - unsigned short device, type; + unsigned short type; ide_drive_t *drive; - + xen_disk_t cur_disk; + for ( loop = 0; loop < MAX_HWIFS; loop++ ) { ide_hwif_t *hwif = &ide_hwifs[loop]; @@ -42,33 +42,42 @@ void ide_probe_devices(xen_disk_info_t* xdi) drive = &hwif->drives[unit]; if ( !drive->present ) continue; + + + /* SMH: don't ever expect this to happen, hence verbose printk */ + if ( xdi->count == xdi->max ) { + printk("ide_probe_devices: out of space for probe.\n"); + return -ENOMEM; + } + + + /* SMH: we export 'raw' linux device numbers to domain 0 */ + cur_disk.device = ide_devs[(loop * MAX_DRIVES) + unit]; + /* ** NB: we use the ide 'media' field (ide_disk, ide_cdrom, etc) ** as our 'type' field (XD_TYPE_DISK, XD_TYPE_CDROM, etc). ** Hence must ensure these are kept in sync. */ - - /* SMH: we export 'raw' linux device numbers to domain 0 */ - device = ide_devs[(loop * MAX_DRIVES) + unit]; - type = drive->media; - capacity = current_capacity(drive); - - xdi->disks[xdi->count].device = device; - xdi->disks[xdi->count].info = type; - + cur_disk.info = (type = drive->media); if(type == XD_TYPE_CDROM) - xdi->disks[xdi->count].info |= XD_FLAG_RO; + cur_disk.info |= XD_FLAG_RO; - xdi->disks[xdi->count].capacity = capacity; - xdi->count++; + cur_disk.capacity = current_capacity(drive); + cur_disk.domain = 0; /* 'physical' disks belong to domain 0 - printk("Device %d: IDE-XENO (%s) capacity %ldkB (%ldMB)\n", - xdi->count, (type == XD_TYPE_DISK) ? "disk" : - ((type == XD_TYPE_CDROM) ? "cdrom" : "unknown"), - capacity>>1, capacity>>11); + /* Now copy into relevant part of user-space buffer */ + if((ret = copy_to_user(xdi->disks + xdi->count, &cur_disk, + sizeof(xen_disk_t))) < 0) { + printk("ide_probe_devices: copy_to_user failed [rc=%d]\n", + ret); + return ret; + } + + xdi->count++; } } - return; + return ret; } diff --git a/xen/drivers/scsi/sd.c b/xen/drivers/scsi/sd.c index 81ef215635..046e2e55ed 100644 --- a/xen/drivers/scsi/sd.c +++ b/xen/drivers/scsi/sd.c @@ -1336,32 +1336,39 @@ static kdev_t scsi_devs[NR_SCSI_DEVS] = { }; -void scsi_probe_devices(xen_disk_info_t *xdi) +int scsi_probe_devices(xen_disk_info_t *xdi) { Scsi_Disk *sd; - int i; - unsigned short device; - unsigned long capacity; + xen_disk_t cur_disk; + int i, ret; for ( sd = rscsi_disks, i = 0; i < sd_template.dev_max; i++, sd++ ) { if ( sd->device == NULL ) continue; + /* SMH: don't ever expect this to happen, hence verbose printk */ + if ( xdi->count == xdi->max ) { + printk("scsi_probe_devices: out of space for probe.\n"); + return -ENOMEM; + } + /* SMH: we export 'raw' linux device numbers to domain 0 */ - device = scsi_devs[i]; - capacity = sd->capacity; - - /* XXX SMH: if make generic, need to properly determine 'type' */ - xdi->disks[xdi->count].device = device; - xdi->disks[xdi->count].info = XD_TYPE_DISK; - xdi->disks[xdi->count].capacity = capacity; - xdi->count++; - - printk("Device %d: SCSI-XENO (disk) capacity %ldkB (%ldMB)\n", - xdi->count, capacity>>1, capacity>>11); + cur_disk.device = scsi_devs[i]; + cur_disk.info = XD_TYPE_DISK; // XXX SMH: should determine properly + cur_disk.capacity = sd->capacity; + cur_disk.domain = 0; // 'physical' disks belong to dom0 + + /* Now copy into relevant part of user-space buffer */ + if((ret = copy_to_user(xdi->disks + xdi->count, &cur_disk, + sizeof(xen_disk_t))) < 0) { + printk("scsi_probe_devices: copy_to_user failed [rc=%d]\n", ret); + return ret; + } + + xdi->count++; } - return; + return 0; } diff --git a/xen/include/hypervisor-ifs/block.h b/xen/include/hypervisor-ifs/block.h index 6d02b4307c..e85ad9f987 100644 --- a/xen/include/hypervisor-ifs/block.h +++ b/xen/include/hypervisor-ifs/block.h @@ -20,8 +20,7 @@ #define XEN_BLOCK_WRITE 1 #define XEN_BLOCK_READA 2 #define XEN_BLOCK_SPECIAL 4 -#define XEN_BLOCK_PROBE 5 /* get config from hypervisor */ -#define XEN_BLOCK_DEBUG 6 /* debug */ +#define XEN_BLOCK_DEBUG 5 /* debug */ /* NB. Ring size must be small enough for sizeof(blk_ring_t) <= PAGE_SIZE. */ #define BLK_RING_SIZE 64 @@ -65,7 +64,6 @@ typedef struct blk_ring_st * Information about the real and virtual disks we have; used during * guest device probing. */ -#define XEN_MAX_DISK_COUNT 64 /* XXX SMH: below types chosen to align with ide_xxx types in ide.h */ #define XD_TYPE_FLOPPY 0x00 @@ -81,19 +79,23 @@ typedef struct blk_ring_st #define XD_FLAG_RO 0x40 #define XD_FLAG_VIRT 0x80 #define XD_READONLY(_x) ((_x) & XD_FLAG_RO) -#define XD_VIRTUAL(_x) ((_x) & XF_FLAG_VIRT) +#define XD_VIRTUAL(_x) ((_x) & XD_FLAG_VIRT) typedef struct xen_disk { unsigned short device; /* device number (opaque 16 bit val) */ unsigned short info; /* device type and flags */ unsigned long capacity; /* size in terms of #512 byte sectors */ + unsigned int domain; /* if a VBD, domain this 'belongs to' */ } xen_disk_t; typedef struct xen_disk_info { - int count; - xen_disk_t disks[XEN_MAX_DISK_COUNT]; + /* IN variables */ + int max; // maximumum number of disks to report + xen_disk_t *disks; // pointer to array of disk info + /* OUT variables */ + int count; // how many disks we have info about } xen_disk_info_t; #endif diff --git a/xen/include/hypervisor-ifs/vbd.h b/xen/include/hypervisor-ifs/vbd.h index c9ac0898c7..53300bdaba 100644 --- a/xen/include/hypervisor-ifs/vbd.h +++ b/xen/include/hypervisor-ifs/vbd.h @@ -13,7 +13,8 @@ #define BLOCK_IO_OP_VBD_ADD 4 /* add an extent to a given VBD */ #define BLOCK_IO_OP_VBD_REMOVE 5 /* remove an extent from a given VBD */ #define BLOCK_IO_OP_VBD_DELETE 6 /* delete a VBD */ - +#define BLOCK_IO_OP_VBD_PROBE 7 /* query VBD information for a domain */ +#define BLOCK_IO_OP_VBD_INFO 8 /* query info about a particular VBD */ typedef struct _xen_extent { u16 device; @@ -32,29 +33,41 @@ typedef struct _xen_extent { typedef struct _vbd_create { - unsigned domain; - u16 vdevice; - u16 mode; + unsigned domain; // create VBD for this domain + u16 vdevice; // 16 bit id domain will refer to VBD as + u16 mode; // OR of { VBD_MODE_R , VBD_MODE_W } } vbd_create_t; typedef struct _vbd_add { - unsigned domain; - u16 vdevice; - xen_extent_t extent; + unsigned domain; // domain in question + u16 vdevice; // 16 bit id domain refers to VBD as + xen_extent_t extent; // the extent to add to this VBD } vbd_add_t; typedef struct _vbd_remove { - unsigned domain; - u16 vdevice; - xen_extent_t extent; + unsigned domain; // domain in question + u16 vdevice; // 16 bit id domain refers to VBD as + xen_extent_t extent; // the extent to remove from this VBD } vbd_remove_t; -typedef struct _vbd_delete { - unsigned domain; - u16 vdevice; +typedef struct _vbd_delete { + unsigned domain; // domain in question + u16 vdevice; // 16 bit id domain refers to VBD as } vbd_delete_t; +#define VBD_PROBE_ALL 0xFFFFFFFF +typedef struct _vbd_probe { + unsigned domain; // domain in question or VBD_PROBE_ALL + xen_disk_info_t xdi; // where's our space for VBD/disk info +} vbd_probe_t; + +typedef struct _vbd_info { + unsigned domain; // domain in question + u16 vdevice; // 16 bit id domain refers to VBD as + u16 nextents; // max no. of extents to return info for + xen_extent_t *extents; // pointer to space for list of extents +} vbd_info_t; typedef struct block_io_op_st @@ -65,10 +78,12 @@ typedef struct block_io_op_st /* no entry for BLOCK_IO_OP_SIGNAL */ /* no entry for BLOCK_IO_OP_RESET */ unsigned long ring_mfn; - vbd_create_t create_info; - vbd_add_t add_info; - vbd_remove_t remove_info; - vbd_delete_t delete_info; + vbd_create_t create_params; + vbd_add_t add_params; + vbd_remove_t remove_params; + vbd_delete_t delete_params; + vbd_probe_t probe_params; + vbd_info_t info_params; } u; } block_io_op_t; diff --git a/xen/include/xeno/vbd.h b/xen/include/xeno/vbd.h index 7e9d4c3fa0..9660756db8 100644 --- a/xen/include/xeno/vbd.h +++ b/xen/include/xeno/vbd.h @@ -30,10 +30,12 @@ typedef struct _vbd { #define VBD_HTAB_SZ 16 // no. of entries in the vbd hash table. -long vbd_create(vbd_create_t *create_info); -long vbd_add(vbd_add_t *add_info); -long vbd_remove(vbd_remove_t *remove_info); -long vbd_delete(vbd_delete_t *delete_info); +long vbd_create(vbd_create_t *create_params); +long vbd_add(vbd_add_t *add_params); +long vbd_remove(vbd_remove_t *remove_params); +long vbd_delete(vbd_delete_t *delete_params); +long vbd_probe(vbd_probe_t *probe_params); +long vbd_info(vbd_info_t *info_params); /* Describes a [partial] disk extent (part of a block io request) */ diff --git a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c index 29619bbbc3..31b06c4c98 100644 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c @@ -22,8 +22,14 @@ static unsigned int state = STATE_SUSPENDED; static blk_ring_t *blk_ring; static unsigned int resp_cons; /* Response consumer for comms ring. */ static unsigned int req_prod; /* Private request producer. */ -static xen_disk_info_t xlblk_disk_info; + +#define XDI_MAX 64 +static xen_disk_info_t xlblk_disk_info; /* information about our disks/VBDs */ + +#if 0 static int xlblk_control_msg_pending; +#endif + /* We plug the I/O ring if the driver is suspended or if the ring is full. */ #define RING_PLUGGED ((BLK_RING_INC(req_prod) == resp_cons) || \ @@ -247,11 +253,13 @@ static int hypervisor_request(unsigned long id, switch ( operation ) { +#if 0 case XEN_BLOCK_PROBE: if ( RING_PLUGGED ) return 1; sector_number = 0; DISABLE_SCATTERGATHER(); break; +#endif case XEN_BLOCK_READ: case XEN_BLOCK_WRITE: @@ -430,9 +438,11 @@ static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs) } break; +#if 0 case XEN_BLOCK_PROBE: xlblk_control_msg_pending = bret->status; break; +#endif default: BUG(); @@ -447,6 +457,7 @@ static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs) } +#if 0 /* Send a synchronous message to Xen. */ int xenolinux_control_msg(int operation, char *buffer, int size) { @@ -472,13 +483,14 @@ int xenolinux_control_msg(int operation, char *buffer, int size) return xlblk_control_msg_pending ? -EINVAL : 0; } +#endif static void reset_xlblk_interface(void) { block_io_op_t op; - xlblk_control_msg_pending = 0; +// xlblk_control_msg_pending = 0; nr_pending = 0; op.cmd = BLOCK_IO_OP_RESET; @@ -500,6 +512,7 @@ static void reset_xlblk_interface(void) int __init xlblk_init(void) { int error; + block_io_op_t op; reset_xlblk_interface(); @@ -511,11 +524,19 @@ int __init xlblk_init(void) goto fail; } + /* Setup our [empty] disk information structure */ + xlblk_disk_info.max = XDI_MAX; + xlblk_disk_info.disks = kmalloc(XDI_MAX * sizeof(xen_disk_t), GFP_KERNEL); + xlblk_disk_info.count = 0; + /* Probe for disk information. */ - memset(&xlblk_disk_info, 0, sizeof(xlblk_disk_info)); - error = xenolinux_control_msg(XEN_BLOCK_PROBE, - (char *)&xlblk_disk_info, - sizeof(xen_disk_info_t)); + memset(&op, 0, sizeof(op)); + op.cmd = BLOCK_IO_OP_VBD_PROBE; + op.u.probe_params.domain = 0; + memcpy(&op.u.probe_params.xdi, &xlblk_disk_info, sizeof(xlblk_disk_info)); + + error = HYPERVISOR_block_io_op(&op); + if ( error ) { printk(KERN_ALERT "Could not probe disks (%d)\n", error); @@ -523,6 +544,9 @@ int __init xlblk_init(void) goto fail; } + /* copy back the [updated] count parameter */ + xlblk_disk_info.count = op.u.probe_params.xdi.count; + /* Pass the information to our virtual block device susbystem. */ xlvbd_init(&xlblk_disk_info); diff --git a/xenolinux-2.4.22-sparse/arch/xeno/drivers/dom0/dom0_core.c b/xenolinux-2.4.22-sparse/arch/xeno/drivers/dom0/dom0_core.c index ff394a0cdd..08144d9678 100644 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/dom0/dom0_core.c +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/dom0/dom0_core.c @@ -65,41 +65,6 @@ static int privcmd_ioctl(struct inode *inode, struct file *file, } break; - case IOCTL_PRIVCMD_BLKMSG: - { - privcmd_blkmsg_t blkmsg; - char *kbuf; - int ret; - - if ( copy_from_user(&blkmsg, (void *)data, sizeof(blkmsg)) ) - return -EFAULT; - - if ( blkmsg.buf_size > PAGE_SIZE ) - return -EINVAL; - - if ( (kbuf = kmalloc(blkmsg.buf_size, GFP_KERNEL)) == NULL ) - return -ENOMEM; - - if ( copy_from_user(kbuf, blkmsg.buf, blkmsg.buf_size) ) { - kfree(kbuf); - return -EFAULT; - } - - ret = xenolinux_control_msg((int)blkmsg.op, kbuf, blkmsg.buf_size); - if ( ret != 0 ) { - kfree(kbuf); - return ret; - } - - if ( copy_to_user(blkmsg.buf, kbuf, blkmsg.buf_size) ) { - kfree(kbuf); - return -EFAULT; - } - - kfree(kbuf); - } - break; - default: ret = -EINVAL; break; -- 2.30.2